﻿partial class Program
{
    internal static async Task MqttTest()
    {
        MqttClientService mqttClientService = new();
        mqttClientService.MqttClientStart();
        Console.ReadLine();
        JsonSerializerOptions options = new()
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        };

        MqttMessageModel<SensorDataPackage> msg = new()
        {
            DeviceCode = "device1",
            DataSerialNumber = 10,
            DeviceType = DeviceType.TubeBelt,
            FunctionCode = FunctionCode.ActiveReport,
            Version = 2,
            Data = [
                new() {
                        GapLocation= 3,
                        Status= TubeBeltState.ReverseWrap,
                        SensorDataList=
                        [
                            23,4,5,6,4,3,4
                        ]
                    }
            ]
        };
        var data = System.Text.Json.JsonSerializer.Serialize(msg, options);
        await mqttClientService.Publish(data);
        Console.ReadLine();
    }
    /// <summary>
    /// 模拟管带巴鲁夫互联网模块
    /// </summary>
    /// <returns></returns>
    internal static async Task SimulateBalluff()
    {
        MqttClientService mqttClientService = new();
        mqttClientService.MqttClientStart();
        var topicTemplate = "balluff/BNI00HP/iolink/devices/mastr1port{0}/processdatabytes/in";
        var dataTemplate = "{\"timestamp\":\"2024-09-04T07:50:38.000Z\",\"type\":\"inputProcessDataBytes\",\"data\":{\"isValid\":true,\"value\":[0,189]}}";
        var rootNode = JsonNode.Parse(dataTemplate)!;
        var dNode = rootNode["data"]!;

        while (true)
        {
            var r = new Random();
            int[][] dataList = Enumerable.Range(0, 7).Select<int, int[]>(x =>
            {
                var v = r.Next(400, 430);
                return [v / 256, v % 256];
            }).ToArray();
            var i = 0;
            foreach (var data in dataList)
            {
                dNode["value"]!.ReplaceWith(data);
                //发向mqtt的信息体json字符串
                var newStr = rootNode.ToJsonString();
                //mqtt主题
                var topic = string.Format(topicTemplate, ++i);
                await mqttClientService.Publish(newStr, topic);
            }
            await Task.Delay(1000);
        }
    }
    static async Task VibratingSensorTest(IServiceProvider serviceProvider)
    {
        (int Id, string Text, string Unit, bool Use)[] dataTypeDescList =
        [
            (0,   "加速度有效值", "m/s^2", true),
            (1,   "速度有效值",   "mm/s", true),
            (2,   "包络值",       "m/s^2", true),
            (3,   "位移",        "um", false),
            (4,   "峭度指标",    "", false),
            (5,   "温度",        "° C", true),
            (8,   "加速度峰峰值", "m/s^", false),
            (9,   "加速度峰值",  "m/s^2", true),
            (10,  "加速度均值",  "m/s^2", false),
            (11,  "波形指标",    "", false),
            (12,  "峰值指标",    "", false),
            (13,  "脉冲指标",    "", false),
            (14,  "裕度指标",    "", false),
            (15,  "峭度",       "", false),
            (16,  "歪度",       "", false),
            (1000,"采集设备电量","", true),
            (1001,"信号强度",    "（RSSI）", true)
        ];
        (int Id, string Text)[] chDescList = [(1, "Z轴"), (2, "X轴"), (3, "Y轴"), (4, "电量"), (5, "温度"), (6, "信号强度")];

        var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
        var optionsBuilder = new MqttClientOptionsBuilder()
            .WithTcpServer("tp-e14-guo-u", 1883)
            .WithClientId("TestApp")
            .WithCleanSession()
            .WithTls(new MqttClientOptionsBuilderTlsParameters
            {
                UseTls = false
            });
        var clientOptions = optionsBuilder.Build();
        var client = new MqttFactory().CreateMqttClient();

        client.ConnectedAsync += async (eventArgs) =>
        {
            logger.LogInformation("MQTT已连接，{@Result}", eventArgs.ConnectResult);
            await client.SubscribeAsync("character");
            await client.SubscribeAsync("wave");
            await client.SubscribeAsync("selftest");
        };
        client.DisconnectedAsync += async (eventArgs) =>
        {
            logger.LogInformation("MQTT已断开，{@Result}", eventArgs.ConnectResult);
        };
        client.ApplicationMessageReceivedAsync += async (eventArgs) =>
        {
            try
            {
                if (eventArgs.ApplicationMessage.Topic == "character")
                {
                    var rp = System.Text.Json.JsonSerializer.Deserialize<VibratingResponse>(eventArgs.ApplicationMessage.Payload, JsonSerializerOptions.Web) ?? throw new Exception();
                    logger.LogInformation("采集数据时间：{Time}，消息ID：{MsgId}，设备号：{DeviceSn}", rp.Time, rp.MsgId, rp.DeviceSn);
                    foreach (var item in rp.Datas)
                    {
                        var (_, chText) = chDescList.First(m => m.Id == item.Ch);
                        foreach (var character in item.Characters)
                        {
                            var (_, typeText, unit, use) = dataTypeDescList.First(m => m.Id == character.Type);
                            if (!use)
                            {
                                continue;
                            }
                            logger.LogInformation("{ChText}-{Text}：{Value} {Unit}", chText, typeText, character.Value, unit);
                        }
                    }

                }
                else if (eventArgs.ApplicationMessage.Topic == "wave")
                {
                    var rp = System.Text.Json.JsonSerializer.Deserialize<VibratingWaveResponse>(eventArgs.ApplicationMessage.Payload, JsonSerializerOptions.Web) ?? throw new Exception();
                    var (_, chText) = chDescList.First(m => m.Id == rp.Channel);
                    logger.LogInformation("波形时间：{WaveTime}，消息ID：{MsgId}，设备号：{DeviceSn}，通道：{Channel}，采样频率：{Fs}，分包序号：{PNum}/{Total}，波形类型：{WaveType}",
                        rp.WaveTime, rp.MsgId, rp.DeviceSn, chText, rp.Fs, rp.PNum + 1, rp.Total, rp.WaveType);
                    logger.LogInformation("波形数据：{Wave}", string.Join(",", rp.Wave.Take(20)));
                }
                else if (eventArgs.ApplicationMessage.Topic == "selftest")
                {
                    var rp = System.Text.Json.JsonSerializer.Deserialize<VibratingSelfTestResponse>(eventArgs.ApplicationMessage.Payload, JsonSerializerOptions.Web) ?? throw new Exception();
                    logger.LogInformation("自检结果：状态：{Status}，IP：{Ip}，掩码：{Mask}，网关：{Gateway}，DNS1：{Dns1}，DNS2：{Dns2}，DHCP：{Dhcp}，网关状态：{GatewayState}，网关序列号：{GatewaySN}",
                        rp.Status, rp.Ip, rp.Mask, rp.Gateway, rp.Dns1, rp.Dns2, rp.Dhcp, rp.GatewayState, rp.GatewaySN);
                    foreach (var state in rp.States)
                    {
                        logger.LogInformation("设备ID：{Id}，状态：{Status}，电量：{Batt}，信号强度：{Issi}，最后在线时间：{LastTime}",
                            state.Id, state.Status, state.Batt, state.Issi, state.LastTime);
                    }
                }
            }
            catch (Exception e)
            {
                logger.LogError(e, "处理振动传感器消息出错");
            }
        };
        await client.ConnectAsync(clientOptions);
        Console.ReadLine();

    }

}
/// <summary>
/// 特征值报文
/// </summary>
class VibratingResponse
{
    /// <summary>
    /// 通道特征值数组
    /// </summary>
    public IEnumerable<VibratingChannel> Datas { get; set; } = [];
    /// <summary>
    /// 设备号
    /// </summary>
    /// <remarks>
    /// 无线传感器终端序列号
    /// </remarks>
    public string DeviceSn { get; set; } = string.Empty;
    /// <summary>
    /// 消息 ID 
    /// </summary>
    /// <remarks>
    /// 消息 ID 标识, 一段时间内不允许重复， 实现策略不限
    /// </remarks>
    public int MsgId { get; set; }
    /// <summary>
    /// 采集时间
    /// </summary>
    public string Time { get; set; } = string.Empty;
}
/// <summary>
/// 通道特征值
/// </summary>
class VibratingChannel
{
    /// <summary>
    /// 通道号
    /// </summary>
    /// <remarks>
    /// 1:Z 轴 2:X 轴 3:Y 轴 4:电量 5:温度 6:信号强度
    /// </remarks>
    public int Ch { get; set; }
    /// <summary>
    /// 单个通道特征值数组
    /// </summary>
    public IEnumerable<VibratingCharacter> Characters { get; set; } = [];
}
/// <summary>
/// 特征值
/// </summary>
class VibratingCharacter
{
    /// <summary>
    /// 特征值类型
    /// </summary>
    /// <remarks>
    /// TypeID 名称 单位 备注
    /// 0 加速度有效值 m/s^2
    /// 1 速度有效值 mm/s
    /// 2 包络值 m/s^2
    /// 3 位移 um
    /// 4 峭度指标
    /// 5 温度 ° C
    /// 8 加速度峰峰值 m/s^2
    /// 9 加速度峰值 m/s^2
    /// 10 加速度均值 m/s^2
    /// 11 波形指标
    /// 12 峰值指标
    /// 13 脉冲指标
    /// 14 裕度指标
    /// 15 峭度
    /// 16 歪度
    /// 1000 采集设备电量 数值乘以 100 转换成%
    /// 1001 信号强度（RSSI）
    /// </remarks>
    public int Type { get; set; }
    /// <summary>
    /// 具体数值
    /// </summary>
    public double Value { get; set; }
}
/// <summary>
/// 波形报文
/// </summary>
class VibratingWaveResponse
{
    /// <summary>
    /// 通道号 1:Z 轴 2:X 轴 3:Y 轴
    /// </summary>
    public int Channel { get; set; }
    /// <summary>
    /// 波形数据编码方式 0： 无（默认）
    /// </summary>
    public int Codec { get; set; }
    /// <summary>
    /// 波形数据转换系数
    /// </summary>
    /// <remarks>
    /// 如果不为 1， 代表 wave 中的各个值乘以 coef 作为最终波形数据
    /// </remarks>
    public int Coef { get; set; }
    /// <summary>
    /// 设备号 无线传感器终端序列号
    /// </summary>
    public string DeviceSn { get; set; } = string.Empty;
    /// <summary>
    /// 采样频率
    /// </summary>
    public int Fs { get; set; }
    /// <summary>
    /// 消息 ID
    /// </summary>
    public int MsgId { get; set; }
    /// <summary>
    /// 分包序号 从 0 开始
    /// </summary>
    public int PNum { get; set; }
    /// <summary>
    /// 总包数
    /// </summary>
    public int Total { get; set; }
    /// <summary>
    /// 单包波形数据 加速度， 单位： m/s^2
    /// </summary>
    public IEnumerable<double> Wave { get; set; } = [];
    /// <summary>
    /// 波形时间， 同一波形的不同分包该值相同
    /// </summary>
    public string WaveTime { get; set; } = string.Empty;
    /// <summary>
    /// 波形类型 0:短波形 1:长波形
    /// </summary>
    public int WaveType { get; set; }
}

/// <summary>
/// 自检报文
/// </summary>
class VibratingSelfTestResponse
{
    /// <summary>
    /// 0： 静态 1： DHCP
    /// </summary>
    public int Dhcp { get; set; }
    public string Dns1 { get; set; } = string.Empty;
    public string Dns2 { get; set; } = string.Empty;
    public string Gateway { get; set; } = string.Empty;
    /// <summary>
    /// 网关终端 SN 号
    /// </summary>
    public string GatewaySN { get; set; } = string.Empty;
    /// <summary>
    /// 网关自检状态 固定值： 0
    /// </summary>
    public int GatewayState { get; set; }
    public string Ip { get; set; } = string.Empty;
    public string Mask { get; set; } = string.Empty;
    public IEnumerable<VibratingSelfTestState> States { get; set; } = [];
    public bool Status { get; set; }
}
/// <summary>
/// 自检状态
/// </summary>
class VibratingSelfTestState
{
    /// <summary>
    /// 传感器电池参考电量 %
    /// </summary>
    public int Batt { get; set; }
    public int Id { get; set; }
    /// <summary>
    /// 信号强度 绝对值， 值越大表示信号越弱
    /// </summary>
    public float Issi { get; set; }
    public string LastTime { get; set; } = string.Empty;
    /// <summary>
    /// 传感器状态
    /// </summary>
    /// <remarks>
    /// 0： 离线（离线状态下的电量值、 信号强度值和时间不做参考）1： 在线
    /// </remarks>
    public int Status { get; set; }
}
